package com.gitee.wsl.serialization.time

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.time.Duration
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.seconds

typealias DurationWithBoxed = @Serializable(with = DurationBoxedSerializer::class) Duration?

object DurationBoxedSerializer : KSerializer<Duration?> {
    @Serializable
    private data class Boxed(
        val seconds: Long = 0L,
        val nanos: Int = 0
    )

    override val descriptor: SerialDescriptor = Boxed.serializer().descriptor
    @OptIn(ExperimentalSerializationApi::class)
    override fun serialize(encoder: Encoder, value: Duration?) {
        encoder.encodeNullableSerializableValue(
            Boxed.serializer(),
            value?.toComponents { seconds, nanoseconds ->
                Boxed(
                    seconds = seconds,
                    nanos = nanoseconds
                )
            }
        )
    }

    @OptIn(ExperimentalSerializationApi::class)
    override fun deserialize(decoder: Decoder): Duration? {
        return decoder.decodeNullableSerializableValue(Boxed.serializer())?.let {
            it.seconds.seconds + it.nanos.nanoseconds
        }
    }
}

